#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>


// 子进程退出可以不等待，直接回收
int main()
{
    signal(SIGCHLD, SIG_IGN); // 收到设置对SIGCHLD进行忽略

    pid_t id = fork();
    if (id == 0)
    {
        // child
        int cnt = 5;
        while (cnt--)
        {
            std::cout << "I am a child process, pid: " << getpid() << std::endl;
            sleep(1);
        }
        exit(1);
    }

    // father
    while(1)
    {
        std::cout << "father running..." << std::endl;
        sleep(1);
    }

    return 0;
}














// 部分进程退出
// void handler(int signo)
// {
//     // 肯定是父进程进行信号捕捉
//     std::cout << "get a sigal: " << signo << ", ppid: " << getpid() << std::endl;
//     while (1)
//     {
//         pid_t rid = waitpid(-1, nullptr, WNOHANG); // 非阻塞
//         if (rid > 0)
//         {
//             std::cout << "wait child success!" << std::endl;
//         }
//         else if(rid < 0)
//         {
//             // 等待失败了，意味着把子进程都回收了，就结束
//             std::cout << "wait process done!" << std::endl;
//             break;
//         }
//         else
//         {
//             std::cout << "wait process done!" << std::endl;
//             break;
//         }
//     }
// }

// 多个进程同时退出
// void handler(int signo)
// {
//     // 肯定是父进程进行信号捕捉
//     std::cout << "get a sigal: " << signo << ", ppid: " << getpid() << std::endl;
//     while (1)
//     {
//         pid_t rid = waitpid(-1, nullptr, 0);
//         if (rid > 0)
//         {
//             std::cout << "wait child success!" << std::endl;
//         }
//         else
//         {
//             // 等待失败了，意味着把子进程都回收了，就结束
//             std::cout << "wait process done!" << std::endl;
//             break;
//         }
//     }
// }

// void DoOtherThing()
// {
//     std::cout << "father process do other thing~" << std::endl;
//     sleep(1);
// }

// int main()
// {
//     signal(SIGCHLD, handler);

//     // 创建多个子进程
//     for (int i = 0; i < 10; i++)
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             // child
//             std::cout << "I am a child process, pid: " << getpid() << std::endl;
//             sleep(3);
//             exit(1);
//         }
//     }

//     // father
//     while (1)
//         DoOtherThing();

//     return 0;
// }











// void handler(int signo)
// {
//     // 肯定是父进程进行信号捕捉
//     std::cout << "get a sigal: " << signo << ", ppid: " << getpid() << std::endl;
//     pid_t rid = waitpid(-1, nullptr, 0);
//     if(rid > 0)
//     {
//         std::cout << "wait child success!" << std::endl;
//     }
// }

// void DoOtherThing()
// {
//     std::cout << "father process do other thing~" << std::endl;
//     sleep(1);
// }

// int main()
// {
//     signal(SIGCHLD, handler);

//     pid_t id = fork();
//     if(id == 0)
//     {
//         // child
//         std::cout << "I am a child process, pid: " << getpid() << std::endl;
//         sleep(3);
//         exit(1);
//     }
//     // father
//     //sleep(50);
//     while(1)
//         DoOtherThing();

//     return 0;
// }








// 子进程退出会给父进程发信号
// void handler(int signo)
// {
//     // 肯定是父进程进行信号捕捉
//     std::cout << "get a sigal: " << signo << ", ppid: " << getpid() << std::endl;
// }

// int main()
// {
//     signal(SIGCHLD, handler);

//     pid_t id = fork();
//     if(id == 0)
//     {
//         // child
//         std::cout << "I am a child process, pid: " << getpid() << std::endl;
//         sleep(3);
//         exit(1);
//     }
//     // father
//     sleep(50);

//     return 0;
// }













// 如果当前正在对2号信号进行处理，默认2号信号会被屏蔽
// 对2号信号处理完成后，会自动解除屏蔽
// void handler(int signum)
// {
//     std::cout << "get a sig: " << signum << std::endl;
//     sleep(100); // 把进程控制在执行2号信号动作这里
//     exit(1);
// }

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_flags = 0;
//     sigemptyset(&act.sa_mask); // 先置空
//     act.sa_handler = handler;

//     sigaction(2, &act, &oact);

//     while(1)
//     {
//         std::cout << "I am a process, pid: " << getpid() << std::endl;
//         sleep(1);
//     }

//     return 0;
// }











// void PrintPending(sigset_t pending)
// {
//     std::cout << "当前进程的pid: " << getpid() << std::endl;
//     std::cout << "当前进程的pending: " << std::endl;
//     for(int signo = 31; signo >= 1; signo--)
//     {
//         // 穷举所有信号，判断该信号是否在pending中
//         if(sigismember(&pending, signo))
//             std::cout << 1;
//         else
//             std::cout << 0;
//     }

//     std::cout << "\n";
// }

// int main()
// {
//     // 1. 屏蔽2号信号
//     sigset_t block_set, old_set;
//     sigemptyset(&block_set);
//     sigemptyset(&old_set);
//     // 把2号信号加入到block表中，此时并没有修改block表
//     sigaddset(&block_set, 2);

//     // 2.真正修改当前进程的内核bolck表，完成屏蔽
//     sigprocmask(SIG_BLOCK, &block_set, &old_set);

//     int cnt = 10;

//     while(1)
//     {
//         // 3.获取当前进程的pending信号集
//         sigset_t pending;
//         sigpending(&pending);

//         // 4.打印pending信号集
//         PrintPending(pending);
//         cnt--;

//         // 5.解除对2号信号的屏蔽
//         if(cnt == 0)
//         {
//             std::cout << "解除对2号信号的屏蔽!!" << std::endl;
//             // 把老的屏蔽字重新设置进去
//             sigprocmask(SIG_SETMASK, &old_set, &block_set);
//         }

//         sleep(1);
//     }
//     return 0;
// }










// int main()
// {
//     while (true)
//     {
//         std::cout << "get pid: " << getpid() << std::endl;

//         int a = 12;
//         a /= 0;

//         // int *p = nullptr;
//         //*p = 20;
//     }
// }




// ./mykill 2 12345
// int main(int argc, char* argv[])
// {
//     if(argc != 3)
//     {
//         std::cout << "Usage: " << argv[0] << " signal pid" << std::endl;
//         return -1;
//     }

//     int sig = std::stoi(argv[1]);
//     pid_t id = std::stoi(argv[2]);

//     kill(id, sig);
// }

// void handler(int sig)
// {
//     std::cout << "get a sig: " << sig << std::endl;
// }






// int main()
// {
//     // 对信号的捕捉，只要捕捉异常，后续一直有效

//     signal(2, handler);
//     while (true)
//     {
//         std::cout << "hello linux, pid: " << getpid() << std::endl;
//         sleep(1);
//     }

//     return 0;
// }